package com.jonyxu.xjojo.base;

import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.lang.Nullable;

import javax.persistence.criteria.*;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

@FunctionalInterface
public interface JojoBaseService<E, ID extends Serializable> {
    public JojoBaseDao<E, ID> getRepository();

    /**
     * 根据ID获取
     * @param id
     * @return
     */
    public default E get(ID id) {
        return getRepository().getOne(id);
    }

    /**
     * 获取所有列表
     * @return
     */
    public default List<E> getAll() {
        return getRepository().findAll();
    }

    /**
     * 获取总数
     * @return
     */
    public default Long getTotalCount() {
        return getRepository().count();
    }

    /**
     * 保存
     * @param entity
     * @return
     */
    public default E save(E entity) {
        return getRepository().save(entity);
    }

    /**
     * 修改
     * @param entity
     * @return
     */
    public default E update(E entity) {
        return getRepository().saveAndFlush(entity);
    }

    /**
     * 批量保存与修改
     * @param entities
     * @return
     */
    public default Iterable<E> saveOrUpdateAll(Iterable<E> entities) {
        return getRepository().saveAll(entities);
    }

    /**
     * 删除
     * @param entity
     */
    public default void delete(E entity) {
        getRepository().delete(entity);
    }

    /**
     * 根据Id删除
     * @param id
     */
    public default void delete(ID id) {
        getRepository().deleteById(id);
    }

    /**
     * 批量删除
     * @param entities
     */
    public default void delete(Iterable<E> entities) {
        getRepository().deleteAll(entities);
    }

    /**
     * 清空缓存，提交持久化
     */
    public default void flush() {
        getRepository().flush();
    }

    /**
     * 根据条件查询获取
     * @param spec
     * @return
     */
    public default List<E> findAll(Specification<E> spec) {
        return getRepository().findAll(spec);
    }

    /**
     * 分页获取
     * @param pageable
     * @return
     */
    public default Page<E> findAll(Pageable pageable){
        return getRepository().findAll(pageable);
    }

    /**
     * 根据查询条件分页获取
     * @param spec
     * @param pageable
     * @return
     */
    public default Page<E> findAll(Specification<E> spec, Pageable pageable) {
        return getRepository().findAll(spec, pageable);
    }

    public default Page<E> findAll(E entity, Pageable pageable) {
        return getRepository().findAll(new Specification<E>() {
            @Nullable
            @Override
            public Predicate toPredicate(Root<E> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {
                List<Predicate> list = new ArrayList<Predicate>();
                Field[] fields = entity.getClass().getDeclaredFields();
                for (Field field : fields) {
                    field.setAccessible(true);

                    //字符串类型
                    String type = field.getType().getName();
                    if (type.equals(java.lang.String.class.getName()) || type.equals(java.lang.Character.class.getName())) {

                        //模糊搜素
                        try {
                            if(field.get(entity) != null && StringUtils.isNotEmpty(String.valueOf(field.get(entity)))){
                                Path<String> columnName = root.get(field.getName());
                                System.out.println(String.valueOf(field.get(entity)));
                                list.add(cb.like(columnName,'%'+String.valueOf(field.get(entity))+'%'));
                            }
                        } catch (IllegalArgumentException e) {
                            e.printStackTrace();

                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        }
                    }
                    //Integer int 类型
                    else if (type.equals(java.lang.Integer.class.getName())){
                        try {
                            if(field.get(entity) != null){
                                Path<Integer> columnName = root.get(field.getName());
                                list.add(cb.equal(columnName, field.get(entity)));
                            }
                        } catch (IllegalArgumentException e) {
                            e.printStackTrace();
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        }
                    }
                    //Long long 类型
                    else if (type.equals(java.lang.Long.class.getName())
                            || type.equals("long")) {
                        try {
                            if(field.get(entity) != null && !"serialVersionUID".equals(field.getName())){
                                Path<Long> columnName = root.get(field.getName());
                                list.add(cb.equal(columnName, field.getLong(entity)));
                            }
                        } catch (IllegalArgumentException e) {
                            e.printStackTrace();
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        }
                    }

//                    //Date 类型
//                    else if (type.equals(java.util.Date.class.getName())) {
//                        try {
//                            if(field.get(entity) != null && StringUtils.isNotEmpty(String.valueOf(field.get(entity)))){
//                                Path<Date> columnName = root.get(field.getName());
//                                list.add(cb.equal(columnName, DateUtil.parse(String.valueOf(field.get(entity)), "yyyy-MM-dd")));
//                            }
//                        } catch (IllegalArgumentException e) {
//                            e.printStackTrace();
//                        } catch (IllegalAccessException e) {
//                            e.printStackTrace();
//                        }
//                    }
                    //Boolean boolean 类型
                    else if (type.equals(java.lang.Boolean.class.getName()) || type.equals("boolean")) {
                        try {
                            if(field.get(entity) != null){
                                Path<Boolean> columnName = root.get(field.getName());
                                list.add(cb.equal(columnName, field.getBoolean(entity)));
                            }
                        } catch (IllegalArgumentException e) {
                            e.printStackTrace();
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        }
                    }
                }

                Predicate[] arr = new Predicate[list.size()];
                cq.where(list.toArray(arr));
                return null;
            }
        }, pageable);
    }

    /**
     * 获取查询条件的结果数
     * @param spec
     * @return
     */
    public default long count(Specification<E> spec) {
        return getRepository().count(spec);
    }
}
